import { getToken } from '@/utils/auth'
import {MessageBox} from "element-ui";
import store from "@/store";

/*
websocket readyState状态
CONNECTING：值为0，表示正在连接。
OPEN：值为1，表示连接成功，可以通信了。
CLOSING：值为2，表示连接正在关闭。
CLOSED：值为3，表示连接已经关闭，或者打开连接失败。
*/

export function WebsocketMessage(bizCode, topic, data){
  return JSON.stringify({
    'bizCode': bizCode,
    'topic': topic,
    'data' : data
  })
}

const ws = {
  state: {
    websocket: null,
    msg: null,
    retryCount: 0,
    callbacks: {},
    isReloginShow: false,
    connecting: false
  },
  mutations: {
    WS_CONNECT: state => {
      console.log("Ws Connecting...", state.connecting)
      let _this = this;
      let token = '';
      if (getToken()) {
        token = 'Bearer ' + getToken()
      }
      if(state.connecting){
        // 如果正在连接
        return
      }
      console.log("websocket实例状态", state.websocket)
      state.connecting = true;
      if(!state.websocket || state.websocket.readyState === 2 || state.websocket.readyState === 3){
        state.websocket = new WebSocket(process.env.VUE_APP_WEBSOCKET_URL + '/' + token);

        state.websocket.onopen = function(res){
          state.retryCount = 0
          state.connecting = false;
          console.log("Ws Connection success...")
        }
        state.websocket.onmessage = function(res){
          // 收到消息
          if(res.data && res.data == 401){
            if (!state.isReloginShow) {
              state.isReloginShow = true;
              MessageBox.confirm('登录状态已过期，您可以继续留在该页面，或者重新登录', '系统提示', {
                confirmButtonText: '重新登录',
                cancelButtonText: '取消',
                type: 'warning'
              }).then(() => {
                state.isReloginShow = false;
                store.dispatch('LogOut').then(() => {
                  // 如果是登录页面不需要重新加载
                  if (window.location.hash.indexOf("#/login") != 0) {
                    location.href = '/index';
                  }
                })
              }).catch(() => {
                state.isReloginShow = false;
              });
            }
            return;
          }
          let data = JSON.parse(res.data)
          console.log('WS收到消息：', data)
          state.msg = data
          let topic = data.topic
          let callback = state.callbacks[topic]
          console.log(topic, state.callbacks, callback)
          if(callback){
            callback.forEach(e=>{
              console.log(111, typeof e)
              if(typeof e == 'function'){
                e(data)
              }
            })
            /*for(let i=0; i<callback.size; i++){
              console.log(111, typeof callback[i])
              if(typeof callback[i] == 'function'){
                callback[i](data)
              }
            }*/
          }
        }
        state.websocket.onclose = function(res){
          console.log("Ws Connection closed...")
          //重连
          ws.mutations.WS_RECONNECT(state)
        }
        state.websocket.onerror = function(res){
          console.log("Connection error...")
          //重连
          ws.mutations.WS_RECONNECT(state)
        }
      }
    },
    WS_RECONNECT: state => {
      //重新连接
      console.log('websocket重新连接')
      let timeout = 1000
      if(state.retryCount > 25){
        timeout = 5000
      }else if(state.retryCount > 50){
        timeout = 10000
      }else if(state.retryCount > 100){
        timeout = 60000
      }else if(state.retryCount > 200){
        timeout = 180000
      }
      setTimeout(ws.mutations.WS_CONNECT(state), timeout)
      state.retryCount ++
    },
    WS_SEND: (state, message) => {
      if(state.websocket == null || state.websocket.readyState != 1){
        console.log("Websocket未连接");
        ws.mutations.WS_RECONNECT(state)
        let that = this
        let retryCount = 0;
        // 尝试等待15次
        let int = setInterval(function(){
          if(retryCount < 15){
            console.log("等待Websocket连接...");
            retryCount ++;
            if(state.websocket != null && state.websocket.readyState == 1){
              state.websocket.send(message)
              console.log("Websocket消息已发送.");
              clearInterval(int)
            }
          }else{
            console.log("WS未连接，放弃Websocket消息发送.");
            clearInterval(int)
          }
        }, 1000)
      }else{
        state.websocket.send(message)
      }
    },
    WS_ADD_CALLBACK: (state, obj) => {
      console.log("WS_ADD_CALLBACK", obj)
      let topic = obj.topic
      let cb = obj.cb
      if(topic && cb){
        let callback = state.callbacks[topic]
        if(!callback){
          callback = new Set()
        }
        callback.add(cb)
        state.callbacks[topic] = callback
      }
    },
    WS_REMOVE_CALLBACK: (state, obj) => {
      console.log("WS_REMOVE_CALLBACK", obj)
      let topic = obj.topic
      let cb = obj.cb
      if(topic && cb){
        let callback = state.callbacks[topic]
        if(callback){
          callback.delete(cb)
        }
        state.callbacks[topic] = callback
      }
    }
  },
  actions: {
    websocketInit({ commit, state }){
      commit('WS_CONNECT')
      console.log(this, state.websocket)
    },
    websocketState({ commit, state }){
      return new Promise((resolve, reject) => {
        resolve(state.websocket)
      })
    },
    websocketSubscribe({ commit }, obj){
      commit('WS_SEND', WebsocketMessage('subscribe', obj.topic, obj.data))
    },
    websocketUnSubscribe({ commit }, obj){
      commit('WS_SEND', WebsocketMessage('unsubscribe', obj.topic, obj.data))
    },
    wsMessageSend({commit}, message){
      commit('WS_SEND', message)
    },
    wsAddCallback({commit}, obj){
      commit('WS_ADD_CALLBACK', obj)
    },
    wsRemoveCallback({commit}, obj){
      commit('WS_REMOVE_CALLBACK', obj)
    }
  }
}

export default ws
